package com.CodeCraft.builder;

import com.CodeCraft.bean.Constants;
import com.CodeCraft.bean.FiledInfo;
import com.CodeCraft.bean.TableInfo;
import com.CodeCraft.utils.DateUtils;
import com.CodeCraft.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;

import java.io.*;

/**
 * <p>
 * 描述: 自动生成PO
 * </p>
 *
 * @author Dorain
 * @version 1.0.0
 * @since 2025/3/31
 */
public class BuildPo {

    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(BuildPo.class);

    public static void execute(TableInfo tableInfo) {
        File folder = new File(Constants.PATH_PO);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        File poFile = new File(folder, tableInfo.getBeanName() + ".java");

        OutputStream out = null;
        OutputStreamWriter outWriter = null;
        BufferedWriter bw = null;


        try {
            out = new FileOutputStream(poFile);
            outWriter = new OutputStreamWriter(out, "utf8");
            bw = new BufferedWriter(outWriter);

            bw.write("package " + Constants.PACKAGE_PO + ";");
            bw.newLine();
            bw.newLine();

            bw.write("import java.io.Serializable;");
            bw.newLine();
            if (tableInfo.isHaveDate() || tableInfo.isHaveDateTime()) {
                bw.write("import java.util.Date;");
                bw.newLine();
                bw.write("import " + Constants.PACKAGE_ENUMS + ".DateTimePatternEnum;");
                bw.newLine();
                bw.write("import " + Constants.PACKAGE_UTILS + ".DateUtils;");
                bw.newLine();
                bw.write(Constants.BEAN_DATE_FORMAT_CLASS + ";");
                bw.newLine();
                bw.write(Constants.BEAN_DATE_UnFORMAT_CLASS + ";");
                bw.newLine();
            }
            //忽略属性
            boolean haveIgnoreBean = false;
            for (FiledInfo filed : tableInfo.getFiledList()) {
                if (ArrayUtils.contains(Constants.IGNORE_BEAN_ToJSON_FIELD.split(","), filed.getPropertyName())) {
                    haveIgnoreBean = true;
                    break;
                }
            }
            if (haveIgnoreBean) {
                bw.write(String.format(Constants.IGNORE_BEAN_ToJSON_CLASS + ";"));
                bw.newLine();
            }
            if (tableInfo.isHaveBigDecimal()) {
                bw.write("import java.math.BigDecimal;");
            }
            bw.newLine();
            bw.newLine();
            //构建类注释
            BuildComment.createClassComment(bw, tableInfo.getComment());
            bw.write("public class " + tableInfo.getBeanName() + " implements Serializable { ");
            bw.newLine();

            for (FiledInfo filed : tableInfo.getFiledList()) {
                BuildComment.createFieldComment(bw, filed.getComment());
                if (ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES, filed.getSqlType())) {
                    bw.write("\t" + String.format(Constants.BEAN_DATE_FORMAT_EXPRESSION, DateUtils.YYYY_MM_DD_HH_MM_SS));
                    bw.newLine();
                    bw.write("\t" + String.format(Constants.BEAN_DATE_UnFORMAT_EXPRESSION, DateUtils.YYYY_MM_DD_HH_MM_SS));
                    bw.newLine();
                }
                if (ArrayUtils.contains(Constants.SQL_DATE_TYPES, filed.getSqlType())) {
                    bw.write("\t" + String.format(Constants.BEAN_DATE_FORMAT_EXPRESSION, DateUtils.YYYY_MM_DD));
                    bw.newLine();
                    bw.write("\t" + String.format(Constants.BEAN_DATE_UnFORMAT_EXPRESSION, DateUtils.YYYY_MM_DD));
                    bw.newLine();
                }


                if (ArrayUtils.contains(Constants.IGNORE_BEAN_ToJSON_FIELD.split(","), filed.getPropertyName())) {
                    bw.write("\t" + String.format(Constants.IGNORE_BEAN_ToJSON_EXPRESSION));
                    bw.newLine();
                }
                bw.write("\tprivate " + filed.getJavaType() + " " + filed.getPropertyName() + ";");
                bw.newLine();
                bw.newLine();
            }
            //getter setter
            for (FiledInfo filed : tableInfo.getFiledList()) {
                String tempField = StringUtils.upperCaseFirstLetter(filed.getPropertyName());
                bw.write("\tpublic void set" + tempField + " (" + filed.getJavaType() + " " + filed.getPropertyName() + ") {");
                bw.newLine();
                bw.write("\t\tthis." + filed.getPropertyName() + " = " + filed.getPropertyName() + ";");
                bw.newLine();
                bw.write("\t}");
                bw.newLine();
                bw.newLine();

                bw.write("\tpublic " + filed.getJavaType() + " get" + tempField + "() {");
                bw.newLine();
                bw.write("\t\treturn this." + filed.getPropertyName() + ";");
                bw.newLine();
                bw.write("\t}");
                bw.newLine();
                bw.newLine();
            }
            StringBuffer toString = new StringBuffer();
            Integer index = 0;
            //重写toString方法
            for (FiledInfo filed : tableInfo.getFiledList()) {
                index++;

                String properName = filed.getPropertyName();
                if (ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES, filed.getSqlType())) {
                    properName = "DateUtils.format(" + properName + ", DateTimePatternEnum.YYYY_MM_DD_HH_MM_SS.getPattern())";
                } else if (ArrayUtils.contains(Constants.SQL_DATE_TYPES, filed.getSqlType())) {
                    properName = "DateUtils.format(" + properName + ", DateTimePatternEnum.YYYY_MM_DD.getPattern())";
                }
                toString.append(filed.getComment() + ":\" + (" + filed.getPropertyName() + " == null ? \"空\": " + properName + ")");
                if (index < tableInfo.getFiledList().size()) {
                    toString.append(" + ").append("\",");

                }
            }
            String toStringStr = toString.toString();
            toStringStr = "\"" + toStringStr;
            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic String toString() {");
            bw.newLine();
            bw.write("\t\treturn " + toStringStr + " ;");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.write("}");
            bw.flush();
        } catch (Exception e) {
            logger.error("生成PO失败", e);
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (outWriter != null) {
                try {
                    outWriter.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
